#region Summary

// 
// Owner : JackieHan 
// 
// Solution : DailyCollection 
// 
// Project : Jackie.Utility.Condition
// 
// File : WordsAnalyseManager.cs
// 
// CopyRight : Copyright © 2010-2011 Skomart Corporation, All Rights Reserved 
// 
// Summary : 词法分析器
// 
// History : 
//			2011-05-20 15:57:08	    Create 
// 

#endregion

#region Using

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jackie.Utility.Condition.Domain;
using Jackie.Utility.Condition.Domain.Define;
using Jackie.Utility.Condition.Domain.Interface;
using Jackie.Utility.Condition.Exception;

#endregion

namespace Jackie.Utility.Condition
{
    /// <summary> 
    /// 词法分析器
    /// </summary>
    public class DefaultWordsAnalyser : IWordAnalyser
    {

        private readonly IList<IDefine> allDefines;
        private readonly IDefine spaceCharacter;

        public DefaultWordsAnalyser()
        {
            allDefines = new List<IDefine>
                             {
                                 new Assignment(),
                                 new Numberic(),
                                 new StringContent(),
                                 new Var(),
                                 new Variable(),
                                 new StatementEndSign(),
                                 new Set(),
                                 new Equal(),
                                 new NotEqual(),
                                 new Greater(),
                                 new GreaterEqual(),
                                 new Less(),
                                 new LessEqual(),
                                 new Negation(),
                                 new ArithmeticSign(),
                                 new CodeBlockEndSign(),
                                 new CodeBlockStartSign(),
                                 new EndBracket(),
                                 new StartBracket(),
                                 new If(),
                                 new For()
                             };
            spaceCharacter = new Space();
        }

        public IList<DefineValue> Analyse(string code)
        {
            var defineValues = new List<DefineValue>();
            var readedString = new StringBuilder();
            IList<IDefine> matchedDefines = new List<IDefine>();
            var readedIndex = 0;
            while (readedIndex <= code.Length)
            {
                //读到字符的末尾，再继续加上一个空格
                char achar = readedIndex + 1 > code.Length ? ' ' : code[readedIndex];

                readedString.Append(achar);
                //匹配已经读到的词
                var matchDefines = allDefines.Where(define => define.Is(readedString.ToString())).ToList();
                //如果本次读取到不是空定义，本次么有匹配到任何定义并且上次匹配结果也是空的则报错
                if (!spaceCharacter.Is(readedString.ToString()) && matchDefines.Count == 0 && matchedDefines.Count == 0)
                    throw new WordNotSupportedException(readedString.ToString());

                if (matchDefines.Count != 0)  //如果有匹配到定义，则保存本地匹配结果，继续读取
                {
                    matchedDefines = matchDefines;
                    readedIndex++;
                    continue;
                }

                //如果本次匹配结果为空且上次匹配的结果不为空，则匹配成功一个定义
                if (matchDefines.Count == 0 && matchedDefines.Count != 0)
                {
                    var wordValue = readedString.ToString(0, readedString.Length - 1);
                    var defineValue = new DefineValue
                                          {
                                              DefineType = GetDefine(matchedDefines, wordValue),
                                              Value = wordValue
                                          };
                    defineValues.Add(defineValue);
                    readedString.Clear();
                    matchedDefines.Clear();
                    if (spaceCharacter.Is(achar.ToString()))
                        readedIndex++;
                }
                else  //本次匹配为空，上次匹配也是空的
                {
                    //如果读取到的字符为空字符，清空本次读取的结果，继续下一个
                    if (spaceCharacter.Is(readedString.ToString()))
                    {
                        readedIndex++;
                        readedString.Clear();
                    }
                }
            }
            return defineValues;
        }

        /// <summary>
        /// 从符合匹配的定义中找到最合适的定义
        /// </summary>
        /// <param name="matchedDefines">匹配结果</param>
        /// <param name="word">复合定义的字符串</param>
        /// <returns></returns>
        private IDefine GetDefine(IList<IDefine> matchedDefines, string word)
        {
            IDefine maxLevelDefine = null;
            foreach (var keyWord in matchedDefines.OfType<IKeyWord>())
            {
                if (keyWord.Lenght == word.Length)
                    maxLevelDefine = keyWord;
            }
            if (maxLevelDefine == null)
            {
                maxLevelDefine = matchedDefines[0];
                if (maxLevelDefine is IKeyWord)
                {
                    throw new WordNotSupportedException(word);
                }
            }
            return maxLevelDefine;
        }
    }
}